﻿//-----------------------------------------------------------------------
// <copyright>
// This file is subject to the terms and conditions of the Microsoft Public License (MS-PL).
// See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL for more details.
// </copyright>
//----------------------------------------------------------------------- 
using System;
using System.Threading;
using Fulcrum.GeneratedCode;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Fulcrum.UnitTests.DispatcherProxies
{
    [TestClass]
    public class MyDispatcherClassProxyTest
    {
        public MyDispatcherClassProxyTest()
        {
            // nothing
        }

        [TestInitialize]
        public void TestInitialize()
        {
            this.uiThreadManager = new UIThreadManager();
            this.uiThreadManager.StartUIThread();

            this.myDispatcherClass = this.uiThreadManager.Invoke<object,MyDispatcherClassTestDouble>( delegate(object param) { return new MyDispatcherClassTestDouble(); }, null);
            this.myDispatcherClassProxy = new MyDispatcherClassProxy(this.myDispatcherClass);
        }

        [TestCleanup]
        public void TestCleanup()
        {
            this.myDispatcherClass = null;
            this.myDispatcherClassProxy = null;

            this.uiThreadManager.StopUIThread();
            this.uiThreadManager = null;

        }

        UIThreadManager uiThreadManager;
        MyDispatcherClassTestDouble myDispatcherClass;
        MyDispatcherClassProxy myDispatcherClassProxy;

        [TestMethod]
        public void TestInnerObject()
        {
            Assert.AreSame(this.myDispatcherClass, this.myDispatcherClassProxy.InnerObject);
        }

        [TestMethod]
        public void TestMethod()
        {
            var result = this.myDispatcherClassProxy.Method(100, "blah");

            Assert.AreEqual(42, result);
            Assert.AreEqual(100, this.myDispatcherClass.MethodParameter1);
            Assert.AreEqual("blah", this.myDispatcherClass.MethodParameter2);
            Assert.AreEqual(this.myDispatcherClass.CallingThreadId, this.uiThreadManager.UIThreadId);
        }

        [TestMethod]
        public void TestProperty()
        {
            var result = this.myDispatcherClassProxy.OverrideReadProperty;

            Assert.AreEqual(383, result);
            Assert.AreEqual(this.myDispatcherClass.CallingThreadId, this.uiThreadManager.UIThreadId);
        }

        [TestMethod]
        public void TestEvent()
        {
            Thread callingThread = null;

            this.myDispatcherClassProxy.OverrideEvent += delegate(object sender, EventArgs e) { callingThread = Thread.CurrentThread; };

            this.myDispatcherClass.RaiseOverrideEvent();

            Assert.IsNotNull(callingThread);
            Assert.AreEqual(Thread.CurrentThread.ManagedThreadId, callingThread.ManagedThreadId);
        }

        class MyDispatcherClassTestDouble : MyDispatcherClass
        {
            public MyDispatcherClassTestDouble()
                : base()
            {
                // nothing
            }

            protected override long OnMethodCalled(int value, string anotherValue)
            {
                SaveCallingThread();

                this.MethodParameter1 = value;
                this.MethodParameter2 = anotherValue;

                return 42;
            }

            protected override int OnOverrideReadProperty()
            {
                SaveCallingThread();

                return 383;
            }

            public void RaiseOverrideEvent()
            {
                this.OnOverrideEvent();
            }

            private void SaveCallingThread()
            {
                this.CallingThreadId = Thread.CurrentThread.ManagedThreadId;
            }

            public int MethodParameter1
            {
                get;
                private set;
            }

            public string MethodParameter2
            {
                get;
                private set;
            }

            public int CallingThreadId
            {
                get;
                private set;
            }

        }

    }
}
